#include<string>
#include<cstring>
#include<iostream>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include"Log.hpp"



class Socket
{
private:
    static const int val_global = 10;
public:
    static int GetSocket()
    {
        int listen_sock = socket(AF_INET,SOCK_STREAM,0);
        if(listen_sock < 0 ) 
        {
            ELOG("%s\n","获取监听套接字失败");
            exit(1);
        }
        int opt = 1;
        setsockopt(listen_sock,SOL_SOCKET,SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)); //地址复用
        return listen_sock;
    }

    static void Bind(int listen_sock , uint16_t port , std::string ip = "0.0.0.0")
    {
        struct sockaddr_in local;
        memset(&local,0,sizeof local);
        local.sin_family = AF_INET;
        local.sin_port = htons(port); 
        inet_pton(AF_INET,ip.c_str(),&local.sin_addr);//ip地址转换成网络序列并填入local.sin_addr
        if(bind(listen_sock,(struct sockaddr*)&local,sizeof local) < 0)
        {
            ELOG("%s\n","绑定端口失败");
            exit(2);
        } 
    }

    static void Listen(int listen_sock)
    {
        if(listen(listen_sock,val_global) < 0 )
        {
            ELOG("%s\n","listen_sock listen fail");
            exit(3);
        }
    }
    static int Accept(int listen_sock,std::string* ip , uint16_t* port)
    {
        struct sockaddr_in peer;
        memset(&peer,0,sizeof peer);
        socklen_t len;
        int new_sock = accept(listen_sock,(struct sockaddr*)&peer,&len); 
        if(new_sock < 0)
        {
            ELOG("%s\n","Server Get Connection Fail");
            return -1;
        }
        if(ip) *ip = inet_ntoa(peer.sin_addr); 
        if(port) *port = ntohs(peer.sin_port); 
        return new_sock; 
    }

    //客户端连接服务器
    static bool Connect(int sock , uint16_t svr_port, std::string svr_ip)
    {
        struct sockaddr_in svr;
        memset(&svr,0,sizeof svr);
        svr.sin_family = AF_INET;
        svr.sin_port = htons(svr_port); 
        inet_pton(AF_INET,svr_ip.c_str(),&svr.sin_addr); 
        
        if(connect(sock,(struct sockaddr*)&svr,sizeof svr) != 0 )
        {
            ELOG("%s\n","Client Get Connection Fail");
            return false;
        }
        return true;
    }
    ~Socket(){}
};